#ifndef EMS_SERVICE_DATA_UPLOADER_H
#define EMS_SERVICE_DATA_UPLOADER_H

#include "device/DeviceBase.h"
#include <memory>
#include <thread>
#include <atomic>
#include <unordered_map>
#include <mutex>

// 前向声明，避免头文件膨胀
namespace ems { namespace protocol { class MqttClient; } }
namespace ems { namespace device { class DeviceManager; } }

namespace ems {
namespace service {

class DataUploader {
public:
    DataUploader();
    ~DataUploader();

    bool initialize();
    void start();
    void stop();

    bool isRunning() const { return running_; }

    // 设置设备管理器引用（用于MQTT同步）
    void setDeviceManager(device::DeviceManager* deviceManager) { deviceManager_ = deviceManager; }

    // 数据分类上报
    void publishDataByCategory(const std::string& deviceId, const std::vector<device::DataValue>& dataValues);

    // 采集回调写入快照（仅赋值，不立即上报）
    void updateSnapshot(const std::string& deviceId, const std::vector<device::DataValue>& dataValues);

    // 采集失败时清空缓存，避免继续上报陈旧数据
    void clearSnapshot(const std::string& deviceId);

    // 从缓存中查询指定设备数据点，返回是否命中
    bool tryGetCachedValue(const std::string& deviceId,
                           const std::string& key,
                           device::DataValue& out) const;

    bool isMqttConnected() const { return mqttConnected_.load(); }
    uint64_t getMessagesSent() const { return messagesSent_.load(); }
    uint64_t getMessagesFailed() const { return messagesFailed_.load(); }
    long long getLastPublishTimestampMs() const { return lastPublishMs_.load(); }
    void rebuildDeviceIntervals();
    std::unordered_map<std::string, std::vector<device::DataValue>> getSnapshotCopy() const;

private:
    std::atomic<bool> running_;
    std::thread uploaderThread_;

    // 设备管理器引用（用于MQTT同步）
    device::DeviceManager* deviceManager_;

    // MQTT 连接
    std::unique_ptr<protocol::MqttClient> mqtt_;
    std::atomic<bool> mqttConnected_{false};
    std::atomic<uint64_t> messagesSent_{0};
    std::atomic<uint64_t> messagesFailed_{0};
    std::atomic<long long> lastPublishMs_{0};
    
    // 动态注册状态
    enum class RegistrationState {
        NOT_REGISTERED,
        REGISTERING,
        REGISTERED,
        FAILED
    };
    std::atomic<RegistrationState> registrationState_{RegistrationState::NOT_REGISTERED};
    std::string deviceSecret_;
    std::atomic<bool> reauthAttempted_{false};
    
    // 设备与主题
    std::string deviceSn_;
    std::string deviceType_;
    std::string topicLogin_;
    std::string topicDataUpload_;
    std::string topicAlarmUpload_;
    std::string topicAlarmClear_;
    std::string topicDeviceSyncResp_;
    std::string topicCommandResp_;
    
    // 上报节流
    long long lastDataTsMs_{0};
    int uploadIntervalSec_{10};
    bool enableDataUpload_{false};

    // 设备级上报调度
    std::unordered_map<std::string, std::vector<device::DataValue>> snapshot_;
    std::unordered_map<std::string, long long> nextUploadMs_;
    std::unordered_map<std::string, int> deviceUploadIntervalSec_;
    std::unordered_map<std::string, bool> modelEnabled_;
    struct ModelDeviceInfo {
        std::string deviceId;
        std::string category;
        std::string rawCategory;
        std::string deviceSn;
        int deviceType{0};
        std::string deviceName;
        bool enabled{true};
        std::string channelName;
    };
    std::unordered_map<std::string, ModelDeviceInfo> modelDeviceInfo_;
    std::unordered_map<std::string, std::string> modelAlias_;
    mutable std::mutex snapshotMutex_;
    std::atomic<bool> reauthRequested_{false};
    std::atomic<bool> reauthInProgress_{false};

    // 内部辅助
    bool setupMqtt();
    bool setupMqttLogin();  // 使用device_secret进行登录
    void teardownMqtt();
    
    // 认证相关（按文档 v3 计算登录参数）
    static std::string hmacSha256Hex(const std::string& key, const std::string& content);
    static std::string md5Hex(const std::string& content);
    static std::string hexEncode(const unsigned char* data, size_t len);
    static std::string randomDigits(int n);
    static std::string buildSignContent(const std::string& authType,
                                        const std::string& deviceSn,
                                        const std::string& deviceType,
                                        const std::string& random,
                                        int securemode);
    static std::string buildClientId(const std::string& deviceType,
                                     const std::string& deviceSn,
                                     const std::string& authType,
                                     const std::string& random,
                                     int securemode);
    static bool readTextFile(const std::string& path, std::string& out);
    
    // 业务：登录/上报/下行处理
    void publishLogin();
    void publishDataSample();
    void handleIncomingMessage(const std::string& topic, const std::string& payload);
    void handleSyncRequest(const std::string& topic, const std::string& payload);
    void handleFuncRequest(const std::string& topic, const std::string& payload);

    // 动态注册相关
    bool performDynamicRegistration();
    void handleRegistrationResponse(const std::string& topic, const std::string& payload);
    bool saveDeviceSecret(const std::string& secret);
    bool loadDeviceSecret();
    bool removeDeviceSecret();
    static long long nowMs();
    static int extractSeq(const std::string& json, int defaultSeq = 0);
    static std::string normalizeCategory(const std::string& category);
    const ModelDeviceInfo* findModelInfo(const std::string& deviceId, const std::string& category) const;
    std::string makeSubDeviceSn(const std::string& deviceId, const std::string& category) const;
    int resolveModelDeviceType(const std::string& deviceId, const std::string& category) const;
    std::string resolveModelDeviceName(const ModelDeviceInfo& info) const;

    void buildDeviceUploadIntervals();
    void handleReauthentication();

    std::string sanitizeGatewayId() const;

    void uploadLoop();
    void recordPublishResult(bool ok);
};

}  // namespace service
}  // namespace ems

#endif  // EMS_SERVICE_DATA_UPLOADER_H
